bitkeeper revision 1.1564.1.5 (429ccefcMIcuaJH4b_1aAdD0JTIaMg)
authordjm@kirby.fc.hp.com <djm@kirby.fc.hp.com>
Tue, 31 May 2005 20:54:20 +0000 (20:54 +0000)
committerdjm@kirby.fc.hp.com <djm@kirby.fc.hp.com>
Tue, 31 May 2005 20:54:20 +0000 (20:54 +0000)
Two more hyperprivops
Signed-off by: Dan Magenheimer <dan.magenheimer@hp.com>

xen/arch/ia64/hyperprivop.S
xen/arch/ia64/privop.c
xen/arch/ia64/vcpu.c
xen/include/public/arch-ia64.h

index 4c8ebb09fc3e933974e350846b0c337ba3e701ea..a33518e0ac5720cc066ca74cb0cbf1251b367db4 100644 (file)
@@ -32,11 +32,45 @@ GLOBAL_ENTRY(fast_hyperprivop)
        // HYPERPRIVOP_RFI?
        cmp.eq p7,p6=XEN_HYPER_RFI,r17
 (p7)   br.sptk.many hyper_rfi;;
-       // if not rfi, give up for now and do it the slow way
+
+#if 0
+       // HYPERPRIVOP_SSM_I?
+       cmp.eq p7,p6=XEN_HYPER_SSM_I,r17
+(p7)   br.sptk.many hyper_ssm_i;;
+#endif
+
+#if 1
+// hard to test, because only called from rbs_switch
+       // HYPERPRIVOP_COVER?
+       cmp.eq p7,p6=XEN_HYPER_COVER,r17
+(p7)   br.sptk.many hyper_cover;;
+#endif
+
+#if 0 // FIXME: This inexplicably causes the number of ssm_dt's to
+      // skyrocket, thus slowing down everything
+       // HYPERPRIVOP_SSM_DT?
+       cmp.eq p7,p6=XEN_HYPER_SSM_DT,r17
+(p7)   br.sptk.many hyper_ssm_dt;;
+#endif
+
+#if 1
+       // HYPERPRIVOP_RSM_DT?
+       cmp.eq p7,p6=XEN_HYPER_RSM_DT,r17
+(p7)   br.sptk.many hyper_rsm_dt;;
+#endif
+
+       // if not one of the above, give up for now and do it the slow way
        br.sptk.many dispatch_break_fault ;;
 
 // ensure that, if giving up, registers at entry to fast_hyperprivop unchanged
 ENTRY(hyper_rfi)
+#define FAST_HYPERPRIVOP_CNT
+#ifdef FAST_HYPERPRIVOP_CNT
+       movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RFI);;
+       ld8 r21=[r20];;
+       adds r21=1,r21;;
+       st8 [r20]=r21;;
+#endif
        adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
        ld8 r21=[r20];;         // r21 = vcr.ipsr
        extr.u r22=r21,IA64_PSR_BE_BIT,1 ;;
@@ -101,3 +135,129 @@ ENTRY(hyper_rfi)
        ;;
        rfi
        ;;
+
+ENTRY(hyper_cover)
+#ifdef FAST_HYPERPRIVOP_CNT
+       movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_COVER);;
+       ld8 r21=[r20];;
+       adds r21=1,r21;;
+       st8 [r20]=r21;;
+#endif
+       mov r24=cr.ipsr
+       mov r25=cr.iip;;
+       // skip test for vpsr.ic.. it's a prerequisite for hyperprivops
+       cover ;;
+       adds r20=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;;
+       mov r30=cr.ifs;;
+       adds r22=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18
+       ld4 r21=[r20] ;;
+       cmp.eq p6,p7=r21,r0 ;;
+(p6)   st8 [r22]=r30;;
+(p7)   st4 [r20]=r0;;
+       mov cr.ifs=r0;;
+       // adjust return address to skip over break instruction
+       extr.u r26=r24,41,2 ;;
+       cmp.eq p6,p7=2,r26 ;;
+(p6)   mov r26=0
+(p6)   adds r25=16,r25
+(p7)   adds r26=1,r26
+       ;;
+       dep r24=r26,r24,41,2
+       ;;
+       mov cr.ipsr=r24
+       mov cr.iip=r25
+       mov pr=r31,-1 ;;
+       rfi
+       ;;
+
+#if 1
+// return from metaphysical mode (meta=1) to virtual mode (meta=0)
+ENTRY(hyper_ssm_dt)
+#ifdef FAST_HYPERPRIVOP_CNT
+       movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SSM_DT);;
+       ld8 r21=[r20];;
+       adds r21=1,r21;;
+       st8 [r20]=r21;;
+#endif
+       mov r24=cr.ipsr
+       mov r25=cr.iip;;
+       adds r20=XSI_METAPHYS_OFS-XSI_PSR_IC_OFS,r18 ;;
+       ld4 r21=[r20];;
+       cmp.eq p7,p0=r21,r0     // meta==0?
+(p7)   br.spnt.many    1f ;;   // already in virtual mode
+       mov r22=IA64_KR(CURRENT);;
+       adds r22=IA64_VCPU_META_SAVED_RR0_OFFSET,r22;;
+       ld4 r23=[r22];;
+       mov rr[r0]=r23;;
+       srlz.i;;
+       st4 [r20]=r0 ;;
+       // adjust return address to skip over break instruction
+       extr.u r26=r24,41,2 ;;
+       cmp.eq p6,p7=2,r26 ;;
+(p6)   mov r26=0
+(p6)   adds r25=16,r25
+(p7)   adds r26=1,r26
+       ;;
+       dep r24=r26,r24,41,2
+       ;;
+       mov cr.ipsr=r24
+       mov cr.iip=r25
+1:     mov pr=r31,-1 ;;
+       rfi
+       ;;
+
+// go to metaphysical mode (meta=1) from virtual mode (meta=0)
+ENTRY(hyper_rsm_dt)
+#ifdef FAST_HYPERPRIVOP_CNT
+       movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RSM_DT);;
+       ld8 r21=[r20];;
+       adds r21=1,r21;;
+       st8 [r20]=r21;;
+#endif
+       mov r24=cr.ipsr
+       mov r25=cr.iip;;
+       adds r20=XSI_METAPHYS_OFS-XSI_PSR_IC_OFS,r18 ;;
+       ld4 r21=[r20];;
+       cmp.ne p7,p0=r21,r0     // meta==0?
+(p7)   br.spnt.many    1f ;;   // already in metaphysical mode
+       mov r22=IA64_KR(CURRENT);;
+       adds r22=IA64_VCPU_META_RR0_OFFSET,r22;;
+       ld4 r23=[r22];;
+       mov rr[r0]=r23;;
+       srlz.i;;
+       adds r21=1,r0 ;;
+       st4 [r20]=r21 ;;
+       // adjust return address to skip over break instruction
+       extr.u r26=r24,41,2 ;;
+       cmp.eq p6,p7=2,r26 ;;
+(p6)   mov r26=0
+(p6)   adds r25=16,r25
+(p7)   adds r26=1,r26
+       ;;
+       dep r24=r26,r24,41,2
+       ;;
+       mov cr.ipsr=r24
+       mov cr.iip=r25
+1:     mov pr=r31,-1 ;;
+       rfi
+       ;;
+
+// enable interrupts (and also interrupt collection)
+ENTRY(hyper_ssm_i)
+#ifdef FAST_HYPERPRIVOP_CNT
+       movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SSM_I);;
+       ld8 r21=[r20];;
+       adds r21=1,r21;;
+       st8 [r20]=r21;;
+#endif
+       mov r24=cr.ipsr
+       mov r25=cr.iip;;
+       movl r20=0x100000001;;
+       st8 [r18]=r20;; // turn on both vpsr.i and vpsr.ic
+// FIXME: NEED TO UPDATE IPSR/IIP TO SKIP BREAK INST
+// FIXME: NEED TO CHECK FOR PENDING INTERRUPTS AND DELIVER THEM!
+1:     mov pr=r31,-1 ;;
+       rfi
+       ;;
+#endif
+
index 0fba1d502fb200d2dd9b957f7b37d9c967cbf4d9..d0be05d9e4a2eb8d5963e4b10e7acc9716d6cfb6 100644 (file)
@@ -747,14 +747,16 @@ priv_emulate(VCPU *vcpu, REGS *regs, UINT64 isr)
 #define HYPERPRIVOP_COVER              0x4
 #define HYPERPRIVOP_ITC_D              0x5
 #define HYPERPRIVOP_ITC_I              0x6
-#define HYPERPRIVOP_MAX                        0x6
+#define HYPERPRIVOP_SSM_I              0x7
+#define HYPERPRIVOP_MAX                        0x7
 
 char *hyperpriv_str[HYPERPRIVOP_MAX+1] = {
-       0, "rfi", "rsm.dt", "ssm.dt", "cover", "itc.d", "itc.i",
+       0, "rfi", "rsm.dt", "ssm.dt", "cover", "itc.d", "itc.i", "ssm.i",
        0
 };
 
-unsigned long hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 };
+unsigned long slow_hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 };
+unsigned long fast_hyperpriv_cnt[HYPERPRIVOP_MAX+1] = { 0 };
 
 /* hyperprivops are generally executed in assembly (with physical psr.ic off)
  * so this code is primarily used for debugging them */
@@ -765,13 +767,12 @@ ia64_hyperprivop(unsigned long iim, REGS *regs)
        INST64 inst;
        UINT64 val;
 
-// FIXME: Add instrumentation for these
 // FIXME: Handle faults appropriately for these
        if (!iim || iim > HYPERPRIVOP_MAX) {
                printf("bad hyperprivop; ignored\n");
                return 1;
        }
-       hyperpriv_cnt[iim]++;
+       slow_hyperpriv_cnt[iim]++;
        switch(iim) {
            case HYPERPRIVOP_RFI:
                (void)vcpu_rfi(ed);
@@ -793,6 +794,9 @@ ia64_hyperprivop(unsigned long iim, REGS *regs)
                inst.inst = 0;
                (void)priv_itc_i(ed,inst);
                return 1;
+           case HYPERPRIVOP_SSM_I:
+               (void)vcpu_set_psr_i(ed);
+               return 1;
        }
        return 0;
 }
@@ -981,18 +985,28 @@ int dump_hyperprivop_counts(char *buf)
 {
        int i;
        char *s = buf;
-       s += sprintf(s,"Slow hyperprivops:\n");
+       unsigned long total = 0;
+       for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += slow_hyperpriv_cnt[i];
+       s += sprintf(s,"Slow hyperprivops (total %d:\n",total);
+       for (i = 1; i <= HYPERPRIVOP_MAX; i++)
+               if (slow_hyperpriv_cnt[i])
+                       s += sprintf(s,"%10d %s\n",
+                               slow_hyperpriv_cnt[i], hyperpriv_str[i]);
+       total = 0;
+       for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += fast_hyperpriv_cnt[i];
+       s += sprintf(s,"Fast hyperprivops (total %d:\n",total);
        for (i = 1; i <= HYPERPRIVOP_MAX; i++)
-               if (hyperpriv_cnt[i])
+               if (fast_hyperpriv_cnt[i])
                        s += sprintf(s,"%10d %s\n",
-                               hyperpriv_cnt[i], hyperpriv_str[i]);
+                               fast_hyperpriv_cnt[i], hyperpriv_str[i]);
        return s - buf;
 }
 
 void zero_hyperprivop_counts(void)
 {
        int i;
-       for (i = 0; i <= HYPERPRIVOP_MAX; i++) hyperpriv_cnt[i] = 0;
+       for (i = 0; i <= HYPERPRIVOP_MAX; i++) slow_hyperpriv_cnt[i] = 0;
+       for (i = 0; i <= HYPERPRIVOP_MAX; i++) fast_hyperpriv_cnt[i] = 0;
 }
 
 #define TMPBUFLEN 8*1024
index ac933c6f6de8927506c9a61d700cbf6427e0317e..b55e5b6bd7bdfb6b6412f984e512354af263dc76 100644 (file)
@@ -173,6 +173,7 @@ IA64FAULT vcpu_set_psr_dt(VCPU *vcpu)
 IA64FAULT vcpu_set_psr_i(VCPU *vcpu)
 {
        PSCB(vcpu,interrupt_delivery_enabled) = 1;
+       PSCB(vcpu,interrupt_collection_enabled) = 1;
        return IA64_NO_FAULT;
 }
 
@@ -649,6 +650,7 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
 #ifdef HEARTBEAT_FREQ
 #define N_DOMS 16      // period in seconds
        static long count[N_DOMS] = { 0 };
+       static long nonclockcount[N_DOMS] = { 0 };
        REGS *regs = vcpu_regs(vcpu);
        unsigned domid = vcpu->domain->domain_id;
 #endif
@@ -670,15 +672,15 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
        }
 #ifdef HEARTBEAT_FREQ
        if (domid >= N_DOMS) domid = N_DOMS-1;
-       if (vector == (PSCB(vcpu,itv) & 0xff) &&
-           !(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) {
-               printf("Dom%d heartbeat... iip=%p,psr.i=%d,pend=%d\n",
-                       domid, regs->cr_iip,
-                       current->vcpu_info->arch.interrupt_delivery_enabled,
-                       current->vcpu_info->arch.pending_interruption);
-               count[domid] = 0;
-               dump_runq();
+       if (vector == (PSCB(vcpu,itv) & 0xff)) {
+           if (!(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) {
+               printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
+                       domid, count[domid], nonclockcount[domid]);
+               //count[domid] = 0;
+               //dump_runq();
+           }
        }
+       else nonclockcount[domid]++;
 #endif
        // now have an unmasked, pending, deliverable vector!
        // getting ivr has "side effects"
index ebae4b89c3044af747451d8133b80f080a78a679..587487640f5cb0de88d525f8958e482588dee97a 100644 (file)
@@ -82,10 +82,11 @@ typedef struct vcpu_guest_context {
 #endif /* !__ASSEMBLY__ */
 
 #define        XEN_HYPER_RFI                   1
-#define        XEN_HYPER_RSM_PSR_DT            2
-#define        XEN_HYPER_SSM_PSR_DT            3
+#define        XEN_HYPER_RSM_DT                2
+#define        XEN_HYPER_SSM_DT                3
 #define        XEN_HYPER_COVER                 4
 #define        XEN_HYPER_ITC_D                 5
 #define        XEN_HYPER_ITC_I                 6
+#define        XEN_HYPER_SSM_I                 7
 
 #endif /* __HYPERVISOR_IF_IA64_H__ */